package com.iteaj.util.json.fastjson;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONPath;
import com.iteaj.util.CommonUtils;
import com.iteaj.util.json.AbstractJson;
import com.iteaj.util.json.Json;
import com.iteaj.util.json.JsonArray;
import com.iteaj.util.json.Type;

import java.beans.Transient;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * create time: 2018/3/29
 *
 * @author iteaj
 * @version 1.0
 * @since 1.7
 */
public class Fastjson extends AbstractJson<JSON> {

    private JSON json;

    public Fastjson(JSON json) {
        this.json = json;
    }

    @Override
    @Transient
    public Type getType() {
        return Type.FastJson;
    }

    @Override
    public JSON original() {
        return this.json;
    }

    @Override
    public int size() {
        return getObject().size();
    }

    @Override
    public Json append(String name, Object val) {
        getObject().put(name, val);
        return this;
    }

    @Override
    public Json remove(String name) {
        getObject().remove(name);
        return this;
    }

    @Override
    public boolean isExist(String name) {
        return getObject().containsKey(name);
    }

    @Override
    public boolean isNull(String name) {
        return getObject().get(name) == null;
    }

    @Override
    public boolean booleanValue(String name) {
        return getObject().getBooleanValue(name);
    }

    @Transient
    protected JSONObject getObject() {
        if(json instanceof JSONObject)
            return (JSONObject) json;

        throw new IllegalStateException("只有JSONObject对象才允许的操作");
    }

    @Override
    public String toJsonString() {
        return original().toJSONString();
    }

    @Override
    public Optional<Boolean> getBoolean(String name) {
        Boolean o = getObject().getBoolean(name);
        return Optional.ofNullable(o);
    }

    @Override
    public short shortValue(String name) {
        return getObject().getShortValue(name);
    }

    @Override
    public Optional<Short> getShort(String name) {
        return Optional.ofNullable(getObject().getShort(name));
    }

    @Override
    public int intValue(String name) {
        return getObject().getInteger(name);
    }

    @Override
    public Optional<Integer> getInt(String name) {
        return Optional.ofNullable(getObject().getInteger(name));
    }

    @Override
    public long longValue(String name) {
        return getObject().getLongValue(name);
    }

    @Override
    public Optional<Long> getLong(String name) {
        return Optional.ofNullable(getObject().getLong(name));
    }

    @Override
    public float floatValue(String name) {
        return getObject().getFloatValue(name);
    }

    @Override
    public Optional<Float> getFloat(String name) {
        return Optional.ofNullable(getObject().getFloat(name));
    }

    @Override
    public double doubleValue(String name) {
        return getObject().getDoubleValue(name);
    }

    @Override
    public Optional<Double> getDouble(String name) {
        return Optional.ofNullable(getObject().getDouble(name));
    }

    @Override
    public Optional<BigDecimal> getBigDecimal(String name) {
        return Optional.ofNullable(getObject().getBigDecimal(name));
    }

    @Override
    public Optional<Date> getDate(String name) {
        return Optional.ofNullable(getObject().getDate(name));
    }

    @Override
    public <E extends Enum> E enumValue(String name, Class<E> clazz) {
        return getObject().getObject(name, clazz);
    }

    @Override
    public <E extends Enum> Optional<E> getEnum(String name, Class<E> clazz) {
        return getString(name).map(val -> (E) Enum.valueOf(clazz, val));
    }

    @Override
    public String stringValue(String name) {
        return getObject().getString(name);
    }

    @Override
    public Optional<String> getString(String name) {
        return Optional.ofNullable(getObject().getString(name));
    }

    @Override
    public <R> R toBean(Class<R> clazz) {
        return original().toJavaObject(clazz);
    }

    @Override
    public JsonArray toJsonArray() {
        return original() instanceof JSONArray ?
                new FastJsonArray((JSONArray) original()) : null;
    }

    @Override
    public Optional<JsonArray> isJsonArray(String name) {
        Object o = getObject().get(name);
        return Optional.ofNullable(o)
                .filter(item -> item instanceof JSONArray)
                .map(val -> new FastJsonArray((JSONArray) val));
    }

    @Override
    public Optional<Json> isJson(String name) {
        Object o = getObject().get(name);
        return Optional.ofNullable(o)
                .filter(item -> item instanceof JSONObject)
                .map(val -> new Fastjson((JSON) val));
    }

    @Override
    public <R> Optional<R> getPath(String path) {
        if(CommonUtils.isBlank(path)) {
            throw new IllegalArgumentException("[path]不能为空");
        }

        String[] split = path.split("/", -1);

        if(!CommonUtils.isNotEmpty(split)) {
            throw new IllegalArgumentException("path必须是格式[/a/b]");
        }

        String jsonPath = Arrays.stream(split).filter(item -> CommonUtils.isNotBlank(item))
                .collect(Collectors.joining(".", "$.", ""));

        Object eval = JSONPath.eval(original(), jsonPath);

        if(eval instanceof JSONArray)
            return Optional.ofNullable(eval).map(val -> (R) new FastJsonArray((JSONArray) val));
        else if(eval instanceof JSONObject)
            return Optional.ofNullable(eval).map(val -> (R) new Fastjson((JSON) val));
        else return Optional.ofNullable(eval).map(val -> (R) eval);
    }
}
